import socket
import random
import threading
import time
import sys
from netadapter import NetAdapter

##
# Cliente
# efetuara as acoes de compra de ingressos do site
#
class Cliente:
    ##
    # Construtor
    # Inicializa servidor com parametros do servidor
    # @param host ip/nome do servidor
    # @param port porta de conexao
    def __init__(self,host,port):
        print '> Cliente: init e conecta no server'
        self.__na = NetAdapter()
        self.__na.conecta(host, port)
        self.__listaProd = []
        self.__carrinhoProd = []
        self.__carrinhoQnt  = []
        self.__carrinhoDisp = []
	print '  Cliente: conectado com sucesso.'       

    ##
    # desconecta
    # desconecta cliente do servidor
    #
    def desconecta(self):
        self.__na.desconecta()
        print '>  cliente desconectado'


    ##
    # Solicita a lista de produtos ao servidor conectado e armazena
    # no atributo listaProd 
    #
    def requisitaInfoProdutos(self):
        print '> Cliente: Solicita lista Produtos'
        self.__na.envia("list")
        #recebe dados
        tmpData = self.__na.recebe()
    	for elem in tmpData.split('\n'):
            if not (elem == ''):
                self.__listaProd.append(elem.split(':'))
        print '  Cliente: total produtos: ' + str(len(self.__listaProd))

    ##
    # getListaProdutos
    # devolve a lista de produtos do servidor 
    # @return tupla das lista de produto e quantidade
    def getListaProdutos(self):
        if (len(self.__listaProd) == 0):
            self.requisitaInfoProdutos()
        return self.__listaProd
            
    ##
    # requisitaInfoProduto
    # Solicita a lista de produtos ao servidor conectado
    # @param  prod produto requisitado
    # @return quantidade do produto
    def requisitaInfoProduto(self, prod): 
        print '> Cliente: Solicita Info Produto ' + prod
        qnt = 0
        if (len(self.__listaProd) == 0):
            self.requisitaInfoProdutos()
        for elem in self.__listaProd:
            if (elem[0] == prod):
                qnt = elem[1]
        print '  Cliente: qnt do produto ' + prod + ' = ' + qnt
        return qnt
    
    ## 
    # compraProduto
    # Solicita quantidade de um produto especifico
    # se o produto jah estiver na lista adiciona a quantidade
    # senao adiciona produto e quantidade
    # @param produto nome do produto desejado
    # @param qnt que deseja comprar
    # @return quantidade que foi alocada para compra
    def compraProduto(self, prod, qnt):
        print '> Cliente: solicitar compra Produto ' + prod
        qntDisponivel = 0
        qntPedida = qnt
        if (len(self.__listaProd) == 0):
            self.requisitaInfoProdutos()
        
        for elem in self.__listaProd:
            if (elem[0] == prod):
                qntDisponivel = int(elem[1])
        
        print '  Cliente: qnt disponivel : ' + str(qntDisponivel)
        
        posItem = -1
        if (prod in self.__carrinhoProd):
            posItem = self.__carrinhoProd.index(prod)
    
        if ( posItem <> -1):
            qntPedida += self.__carrinhoQnt[posItem]
            self.__carrinhoQnt[posItem] = qntPedida
        else:
            self.__carrinhoProd.append(prod)
            self.__carrinhoQnt.append(qntPedida)
        print '  Cliente: qnt alocada do produto ' + self.__carrinhoProd[posItem] + ' = ' + str(self.__carrinhoQnt[posItem])
        return qntPedida
    
    ##
    # finalizaCompra
    # Efetua a compra de um ou mais produtos
    #  o produto eh alocado ou nao para compra conforme resposta do servidor
    def finalizaCompra(self):
        print '> Cliente: finalizaCompra Produto'
        novoCarrinho = []
        for i in range(0,len(self.__carrinhoProd)):
            print '  Cliente: compra '+str(self.__carrinhoQnt[i])+' de '+ self.__carrinhoProd[i]
            msg = 'sub:'+self.__carrinhoProd[i]+':'+str(self.__carrinhoQnt[i])
            self.__na.envia(msg)
            resp = self.__na.recebe().split(':')
            print resp[0], resp[1], resp[2]
            print '  Cliente: servidor alocou '+resp[1]+' de '+ self.__carrinhoProd[i]
            if (resp[1] == self.__carrinhoQnt[i]):
                self.__carrinhoDisp.append(0)
            else:
                self.__carrinhoDisp.append(int(resp[2]))
                
    ##
    # trataRespostaCompra
    # decide por comprar ou nao a quantidade dada como disponivel pelo servidor
    #
    def trataRespostaCompra(self):
        print '> Cliente: trataRespostaCompra'
        for i in range(0,len(self.__carrinhoProd)):
            if (random.randint(0,1) == 1):
                while(self.__carrinhoDisp[i] > 0):
                    print '  Cliente: compra '+str(self.__carrinhoDisp[i])+' de '+ self.__carrinhoProd[i]
                    msg = 'sub:'+self.__carrinhoProd[i]+':'+str(self.__carrinhoDisp[i])
                    self.__na.envia(msg)
                    resp = self.__na.recebe().split(':')
                    print '  Cliente: servidor alocou '+resp[1]+' de '+ self.__carrinhoProd[i]
                    if (resp[1] == self.__carrinhoQnt[i]):
                        self.__carrinhoDisp[i] = 0
                    else:
                        self.__carrinhoDisp[i] = resp[2]
        self.__carrinhoProd = []
        self.__carrinhoQnt  = []
        self.__carrinhoDisp = []
    
##
# rodaClienteAutonomo
# gera um cliente e faz ele realizar uma compra
# @param host ip/nome do servidor
# @param port porta de conexao
def rodaClienteAutonomo(host,port):
    print '> Cliente: rodaClienteAutonomo'
    cliente = Cliente(host,port)
    prod = cliente.getListaProdutos()
    nbProd = random.randint(0, len(prod))
    for i in range(0,nbProd):
        prodEscolhido = random.randint(0, len(prod)-1)
        print '  produto escolhido = ' + str(prodEscolhido)
        qntEscolhida = random.randint(0,10)
        cliente.compraProduto(prod[prodEscolhido][0],qntEscolhida)
    cliente.finalizaCompra()
    cliente.trataRespostaCompra()
    cliente.desconecta()


##
# geraClientees
# gera varios clientes e 
# @param host ip/nome do servidor
# @param port porta de conexao
# @param nb numero de clientes a serem gerados
def geraClientes(host, port, nb):
    print '> Cliente: geraClientes'
    listaThreads = []
    for i in range(0,nb):
        thread = threading.Thread( target=rodaClienteAutonomo, args=(host,port) )
        thread.start()
    for i in range(0, len(listaThreads)):
        thread.exit()
        
        
#executa
host = sys.argv[1]
port = int(sys.argv[2])
qnt = int(sys.argv[3])
geraClientes(host, port, qnt)
